<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta name="theme-color" content="#222"><meta name="generator" content="Hexo 6.3.0">

  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">



<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css" integrity="sha256-Z1K5uhUaJXA7Ll0XrZ/0JhX4lAtZFpT6jkKrEDT0drU=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.1.1/animate.min.css" integrity="sha256-PR7ttpcvz8qrF57fur/yAx1qXMFJeJFiA6pSzWi0OIE=" crossorigin="anonymous">

<script class="next-config" data-name="main" type="application/json">{"hostname":"example.com","root":"/","images":"/images","scheme":"Muse","darkmode":false,"version":"8.14.1","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12},"copycode":{"enable":false,"style":null},"bookmark":{"enable":false,"color":"#222","save":"auto"},"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"stickytabs":false,"motion":{"enable":true,"async":false,"transition":{"menu_item":"fadeInDown","post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"prism":false,"i18n":{"placeholder":"搜索...","empty":"没有找到任何搜索结果：${query}","hits_time":"找到 ${hits} 个搜索结果（用时 ${time} 毫秒）","hits":"找到 ${hits} 个搜索结果"},"path":"/search.xml","localsearch":{"enable":true,"trigger":"auto","top_n_per_article":-1,"unescape":false,"preload":false}}</script><script src="/js/config.js"></script>

    <meta name="description" content="什么是文件描述符简介文件描述符在形式上是一个非负整数。实际上，它是一个索引值，指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时，内核向进程返回一个文件描述符。在程序设计程序设计)中，一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于UNIX、Linux这样的操作系统。 每个Unix进程（除了可能的守护进程）应均有三个标">
<meta property="og:type" content="article">
<meta property="og:title" content="Linux文件描述符的使用与实现">
<meta property="og:url" content="http://example.com/2021/11/20/Linux%E6%96%87%E4%BB%B6%E6%8F%8F%E8%BF%B0%E7%AC%A6%E7%9A%84%E5%AE%9E%E7%8E%B0/index.html">
<meta property="og:site_name" content="JsyBlog">
<meta property="og:description" content="什么是文件描述符简介文件描述符在形式上是一个非负整数。实际上，它是一个索引值，指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时，内核向进程返回一个文件描述符。在程序设计程序设计)中，一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于UNIX、Linux这样的操作系统。 每个Unix进程（除了可能的守护进程）应均有三个标">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="http://example.com/2021/11/20/Linux%E6%96%87%E4%BB%B6%E6%8F%8F%E8%BF%B0%E7%AC%A6%E7%9A%84%E5%AE%9E%E7%8E%B0/fd2.png">
<meta property="og:image" content="http://example.com/2021/11/20/Linux%E6%96%87%E4%BB%B6%E6%8F%8F%E8%BF%B0%E7%AC%A6%E7%9A%84%E5%AE%9E%E7%8E%B0/fd1.png">
<meta property="article:published_time" content="2021-11-20T14:15:56.000Z">
<meta property="article:modified_time" content="2022-03-28T07:28:41.027Z">
<meta property="article:author" content="SongyangJi">
<meta property="article:tag" content="Linux">
<meta property="article:tag" content="File">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="http://example.com/2021/11/20/Linux%E6%96%87%E4%BB%B6%E6%8F%8F%E8%BF%B0%E7%AC%A6%E7%9A%84%E5%AE%9E%E7%8E%B0/fd2.png">


<link rel="canonical" href="http://example.com/2021/11/20/Linux%E6%96%87%E4%BB%B6%E6%8F%8F%E8%BF%B0%E7%AC%A6%E7%9A%84%E5%AE%9E%E7%8E%B0/">



<script class="next-config" data-name="page" type="application/json">{"sidebar":"","isHome":false,"isPost":true,"lang":"zh-CN","comments":true,"permalink":"http://example.com/2021/11/20/Linux%E6%96%87%E4%BB%B6%E6%8F%8F%E8%BF%B0%E7%AC%A6%E7%9A%84%E5%AE%9E%E7%8E%B0/","path":"2021/11/20/Linux文件描述符的实现/","title":"Linux文件描述符的使用与实现"}</script>

<script class="next-config" data-name="calendar" type="application/json">""</script>
<title>Linux文件描述符的使用与实现 | JsyBlog</title>
  








  <noscript>
    <link rel="stylesheet" href="/css/noscript.css">
  </noscript>
</head>

<body itemscope itemtype="http://schema.org/WebPage" class="use-motion">
  <div class="headband"></div>

  <main class="main">
    <div class="column">
      <header class="header" itemscope itemtype="http://schema.org/WPHeader"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏" role="button">
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <i class="logo-line"></i>
      <p class="site-title">JsyBlog</p>
      <i class="logo-line"></i>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger" aria-label="搜索" role="button">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>



<nav class="site-nav">
  <ul class="main-menu menu"><li class="menu-item menu-item-home"><a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a></li><li class="menu-item menu-item-tags"><a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a></li><li class="menu-item menu-item-categories"><a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a></li><li class="menu-item menu-item-archives"><a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a></li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup"><div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off" maxlength="80"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close" role="button">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div class="search-result-container no-result">
  <div class="search-result-icon">
    <i class="fa fa-spinner fa-pulse fa-5x"></i>
  </div>
</div>

    </div>
  </div>

</header>
        
  
  <aside class="sidebar">

    <div class="sidebar-inner sidebar-nav-active sidebar-toc-active">
      <ul class="sidebar-nav">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <div class="sidebar-panel-container">
        <!--noindex-->
        <div class="post-toc-wrap sidebar-panel">
            <div class="post-toc animated"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%BB%80%E4%B9%88%E6%98%AF%E6%96%87%E4%BB%B6%E6%8F%8F%E8%BF%B0%E7%AC%A6"><span class="nav-number">1.</span> <span class="nav-text">什么是文件描述符</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%AE%80%E4%BB%8B"><span class="nav-number">1.1.</span> <span class="nav-text">简介</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%B8%8E%E6%96%87%E4%BB%B6%E6%8F%8F%E8%BF%B0%E7%AC%A6%E7%9B%B8%E5%85%B3%E7%9A%84%E6%93%8D%E4%BD%9C"><span class="nav-number">1.2.</span> <span class="nav-text">与文件描述符相关的操作</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%96%87%E4%BB%B6%E6%8F%8F%E8%BF%B0%E7%AC%A6%E7%9A%84%E7%94%9F%E6%88%90"><span class="nav-number">1.2.1.</span> <span class="nav-text">文件描述符的生成</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%B8%8E%E5%8D%95%E4%B8%80%E6%96%87%E4%BB%B6%E6%8F%8F%E8%BF%B0%E7%AC%A6%E7%9B%B8%E5%85%B3%E7%9A%84%E6%93%8D%E4%BD%9C"><span class="nav-number">1.2.2.</span> <span class="nav-text">与单一文件描述符相关的操作</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%B8%8E%E5%A4%8D%E6%95%B0%E6%96%87%E4%BB%B6%E6%8F%8F%E8%BF%B0%E7%AC%A6%E7%9B%B8%E5%85%B3%E7%9A%84%E6%93%8D%E4%BD%9C"><span class="nav-number">1.2.3.</span> <span class="nav-text">与复数文件描述符相关的操作</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%B8%8E%E6%96%87%E4%BB%B6%E6%8F%8F%E8%BF%B0%E7%AC%A6%E8%A1%A8%E7%9B%B8%E5%85%B3%E7%9A%84%E6%93%8D%E4%BD%9C"><span class="nav-number">1.2.4.</span> <span class="nav-text">与文件描述符表相关的操作</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%94%B9%E5%8F%98%E8%BF%9B%E7%A8%8B%E7%8A%B6%E6%80%81%E7%9A%84%E6%93%8D%E4%BD%9C"><span class="nav-number">1.2.5.</span> <span class="nav-text">改变进程状态的操作</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%B8%8E%E6%96%87%E4%BB%B6%E5%8A%A0%E9%94%81%E7%9A%84%E6%93%8D%E4%BD%9C"><span class="nav-number">1.2.6.</span> <span class="nav-text">与文件加锁的操作</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%B8%8E%E5%A5%97%E6%8E%A5%E5%AD%97%E7%9B%B8%E5%85%B3%E7%9A%84%E6%93%8D%E4%BD%9C"><span class="nav-number">1.2.7.</span> <span class="nav-text">与套接字相关的操作</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E6%96%87%E4%BB%B6%E6%8F%8F%E8%BF%B0%E7%AC%A6%E7%9A%84%E5%AE%9E%E7%8E%B0"><span class="nav-number">2.</span> <span class="nav-text">文件描述符的实现</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%96%87%E4%BB%B6%E6%8F%8F%E8%BF%B0%E7%AC%A6%E8%A1%A8"><span class="nav-number">2.1.</span> <span class="nav-text">文件描述符表</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%96%87%E4%BB%B6%E8%A1%A8%E9%A1%B9"><span class="nav-number">2.2.</span> <span class="nav-text">文件表项</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Inode"><span class="nav-number">2.3.</span> <span class="nav-text">Inode</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%80%BB%E7%BB%93"><span class="nav-number">2.4.</span> <span class="nav-text">总结</span></a></li></ol></li></ol></div>
        </div>
        <!--/noindex-->

        <div class="site-overview-wrap sidebar-panel">
          <div class="site-author animated" itemprop="author" itemscope itemtype="http://schema.org/Person">
  <p class="site-author-name" itemprop="name">SongyangJi</p>
  <div class="site-description" itemprop="description"></div>
</div>
<div class="site-state-wrap animated">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
        <a href="/archives/">
          <span class="site-state-item-count">251</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
          <a href="/categories/">
        <span class="site-state-item-count">45</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
          <a href="/tags/">
        <span class="site-state-item-count">109</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>

        </div>
      </div>
    </div>

    
  </aside>


    </div>

    <div class="main-inner post posts-expand">


  


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://example.com/2021/11/20/Linux%E6%96%87%E4%BB%B6%E6%8F%8F%E8%BF%B0%E7%AC%A6%E7%9A%84%E5%AE%9E%E7%8E%B0/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="SongyangJi">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="JsyBlog">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="post" itemscope itemtype="http://schema.org/CreativeWork">
      <meta itemprop="name" content="Linux文件描述符的使用与实现 | JsyBlog">
      <meta itemprop="description" content="">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          Linux文件描述符的使用与实现
        </h1>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2021-11-20 22:15:56" itemprop="dateCreated datePublished" datetime="2021-11-20T22:15:56+08:00">2021-11-20</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar-check"></i>
      </span>
      <span class="post-meta-item-text">更新于</span>
      <time title="修改时间：2022-03-28 15:28:41" itemprop="dateModified" datetime="2022-03-28T15:28:41+08:00">2022-03-28</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/Linux/" itemprop="url" rel="index"><span itemprop="name">Linux</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
        <h1 id="什么是文件描述符"><a href="#什么是文件描述符" class="headerlink" title="什么是文件描述符"></a>什么是文件描述符</h1><h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>文件描述符在形式上是一个非负整数。实际上，它是一个索引值，指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时，内核向进程返回一个文件描述符。在程序设计程序设计)中，一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于UNIX、Linux这样的操作系统。</p>
<p>每个Unix进程（除了可能的守护进程）应均有三个标准的POSIX文件描述符，对应于三个标准流：</p>
<table>
<thead>
<tr>
<th align="center">整数值</th>
<th align="center">名称</th>
<th align="center">符号常量</th>
<th align="center">文件流</th>
</tr>
</thead>
<tbody><tr>
<td align="center">0</td>
<td align="center"><a target="_blank" rel="noopener" href="https://zh.wikipedia.org/wiki/Stdin">Standard input</a></td>
<td align="center">STDIN_FILENO</td>
<td align="center">stdin</td>
</tr>
<tr>
<td align="center">1</td>
<td align="center"><a target="_blank" rel="noopener" href="https://zh.wikipedia.org/wiki/Stdout">Standard output</a></td>
<td align="center">STDOUT_FILENO</td>
<td align="center">stdout</td>
</tr>
<tr>
<td align="center">2</td>
<td align="center"><a target="_blank" rel="noopener" href="https://zh.wikipedia.org/wiki/Stderr">Standard error</a></td>
<td align="center">STDERR_FILENO</td>
<td align="center">stderr</td>
</tr>
</tbody></table>
<p>文件描述符的优点主要有两个：</p>
<ul>
<li>基于文件描述符的I&#x2F;O操作兼容POSIX标准。</li>
<li>在UNIX、Linux的系统调用中，大量的系统调用都是依赖于文件描述符。</li>
</ul>
<p>例如，下面的代码就示范了如何基于文件描述符来读取当前目录下的一个指定文件，并把文件内容打印至Console中。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdlib.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;string.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;unistd.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/types.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/stat.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;fcntl.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="type">int</span> <span class="title function_">main</span> <span class="params">(<span class="type">void</span>)</span>&#123;</span><br><span class="line">    <span class="type">int</span> fd;</span><br><span class="line">    <span class="type">int</span> numbytes;</span><br><span class="line">    <span class="type">char</span> path[] = <span class="string">&quot;file&quot;</span>;</span><br><span class="line">    <span class="type">char</span> buf[<span class="number">256</span>];</span><br><span class="line"></span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     * O_CREAT:如果文件不存在则创建</span></span><br><span class="line"><span class="comment">     * O_RDONLY:以只读模式打开文件</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    fd = open(path, O_CREAT | O_RDONLY, <span class="number">0644</span>);</span><br><span class="line">    <span class="keyword">if</span>(fd &lt; <span class="number">0</span>)&#123;</span><br><span class="line">        perror(<span class="string">&quot;open()&quot;</span>);</span><br><span class="line">        <span class="built_in">exit</span>(EXIT_FAILURE);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">memset</span>(buf, <span class="number">0x00</span>, <span class="number">256</span>);</span><br><span class="line">    <span class="keyword">while</span>((numbytes = read(fd, buf, <span class="number">255</span>)) &gt; <span class="number">0</span>)&#123;</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">&quot;%d bytes read: %s&quot;</span>, numbytes, buf);</span><br><span class="line">        <span class="built_in">memset</span>(buf, <span class="number">0x00</span>, <span class="number">256</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    close (fd);</span><br><span class="line">    <span class="built_in">exit</span>(EXIT_SUCCESS);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>




<h2 id="与文件描述符相关的操作"><a href="#与文件描述符相关的操作" class="headerlink" title="与文件描述符相关的操作"></a>与文件描述符相关的操作</h2><h3 id="文件描述符的生成"><a href="#文件描述符的生成" class="headerlink" title="文件描述符的生成"></a>文件描述符的生成</h3><ul>
<li>open(), open64(), creat(), creat64()</li>
<li>socket()</li>
<li>socketpair()</li>
<li>pipe()</li>
</ul>
<h3 id="与单一文件描述符相关的操作"><a href="#与单一文件描述符相关的操作" class="headerlink" title="与单一文件描述符相关的操作"></a>与单一文件描述符相关的操作</h3><ul>
<li>read(), write()</li>
<li>recv(), send()</li>
<li>recvmsg(), sendmsg()</li>
<li>sendfile()</li>
<li>lseek(), lseek64()</li>
<li>fstat(), fstat64()</li>
<li>fchmod()</li>
<li>fchown()</li>
</ul>
<h3 id="与复数文件描述符相关的操作"><a href="#与复数文件描述符相关的操作" class="headerlink" title="与复数文件描述符相关的操作"></a>与复数文件描述符相关的操作</h3><ul>
<li>select(), pselect()</li>
<li>poll(),epoll()</li>
</ul>
<h3 id="与文件描述符表相关的操作"><a href="#与文件描述符表相关的操作" class="headerlink" title="与文件描述符表相关的操作"></a>与文件描述符表相关的操作</h3><ul>
<li>close()</li>
<li>dup()</li>
<li>dup2()</li>
<li>fcntl (F_DUPFD)</li>
<li>fcntl (F_GETFD and F_SETFD)</li>
</ul>
<h3 id="改变进程状态的操作"><a href="#改变进程状态的操作" class="headerlink" title="改变进程状态的操作"></a>改变进程状态的操作</h3><ul>
<li>fchdir()</li>
<li>mmap()</li>
</ul>
<h3 id="与文件加锁的操作"><a href="#与文件加锁的操作" class="headerlink" title="与文件加锁的操作"></a>与文件加锁的操作</h3><ul>
<li>flock()</li>
<li>fcntl (F_GETLK, F_SETLK and F_SETLKW)</li>
<li>lockf()</li>
</ul>
<h3 id="与套接字相关的操作"><a href="#与套接字相关的操作" class="headerlink" title="与套接字相关的操作"></a>与套接字相关的操作</h3><ul>
<li>connect()</li>
<li>bind()</li>
<li>listen()</li>
<li>accept()</li>
<li>getsockname()</li>
<li>getpeername()</li>
<li>getsockopt(), setsockopt()</li>
<li>shutdown()</li>
</ul>
<h1 id="文件描述符的实现"><a href="#文件描述符的实现" class="headerlink" title="文件描述符的实现"></a>文件描述符的实现</h1><p><strong>在内核中每一个打开的文件都需要由3种数据结构来进行维护</strong>。</p>
<p> 根据文中内容，这三种数据结构分别为：</p>
<ol>
<li><p>进程级：每个进程对应一张<strong>打开文件描述符表，</strong>这是<strong>进程级</strong>数据结构，也就是每一个进程都各自有这样一个数据结构；</p>
</li>
<li><p>内核级：内核维持一张<strong>打开文件表，文件表由多个文件表项组成，</strong>这是<strong>系统级</strong>数据结构，也就是说这样的数据结构是针对于整个内核而言的，每个进程都可共享的；</p>
</li>
<li><p>系统级：每个打开的文件对应一个<strong>i节点（i-node）</strong>数据结构（Linux下只有i节点没有v节点），由于这是每一个打开的文件与之对应的，因此这也是一个<strong>系统级</strong>数据结构，存在于内核中，非进程所独有。</p>
</li>
</ol>
<p>那么，这三种数据结构到底是什么呢？</p>
<h2 id="文件描述符表"><a href="#文件描述符表" class="headerlink" title="文件描述符表"></a>文件描述符表</h2><p>在Linux中，对于每一个进程，都会分配一个PCB数据结构，它其中包含了该进程的所有信息，而在代码实现上，这个数据结构名为<strong>task_struct</strong>，在linux源码的<strong>include&#x2F;linux&#x2F;sched.h</strong>中可以找到其定义，它是一个很庞大的结构体，部分定义如下：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">task_struct</span> &#123;</span></span><br><span class="line">	......</span><br><span class="line">	<span class="comment">/* CPU-specific state of this task */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">thread_struct</span> <span class="title">thread</span>;</span></span><br><span class="line">	<span class="comment">/* filesystem information */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">fs_struct</span> *<span class="title">fs</span>;</span></span><br><span class="line">	<span class="comment">/* open file information */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">files_struct</span> *<span class="title">files</span>;</span>  <span class="comment">// 注意这个</span></span><br><span class="line">	<span class="comment">/* namespaces */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">nsproxy</span> *<span class="title">nsproxy</span>;</span></span><br><span class="line">	<span class="comment">/* signal handlers */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">signal_struct</span> *<span class="title">signal</span>;</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">sighand_struct</span> *<span class="title">sighand</span>;</span></span><br><span class="line">	......</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>



<p> 在<strong>task_struct</strong>中，有一个成员变量名为<strong>files</strong>，注释中提到这是一个描述打开文件信息的变量，其类型为<strong>struct files_struct *<strong>，那么现在再接着看</strong>files_struct</strong>，在linux源码的<strong>include&#x2F;linux&#x2F;fdtable.h</strong>中可以找到其定义，定义如下：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">files_struct</span> &#123;</span></span><br><span class="line">	<span class="comment">/*</span></span><br><span class="line"><span class="comment">   * read mostly part</span></span><br><span class="line"><span class="comment">   */</span></span><br><span class="line">	<span class="type">atomic_t</span> count;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">fdtable</span> __<span class="title">rcu</span> *<span class="title">fdt</span>;</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">fdtable</span> <span class="title">fdtab</span>;</span></span><br><span class="line">	<span class="comment">/*</span></span><br><span class="line"><span class="comment">   * written part on a separate cache line in SMP</span></span><br><span class="line"><span class="comment">   */</span></span><br><span class="line">	<span class="type">spinlock_t</span> file_lock ____cacheline_aligned_in_smp;</span><br><span class="line">	<span class="type">int</span> next_fd;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">embedded_fd_set</span> <span class="title">close_on_exec_init</span>;</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">embedded_fd_set</span> <span class="title">open_fds_init</span>;</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">file</span> __<span class="title">rcu</span> * <span class="title">fd_array</span>[<span class="title">NR_OPEN_DEFAULT</span>];</span></span><br><span class="line">	<span class="comment">//进程级打开文件描述符表</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>



<p>而这里所要找到的<strong>打开文件描述符表</strong>，实际上就是files_struct 中的成员<strong>struct file * fd_array[NR_OPEN_DEFAULT]<strong>它是一个指针数组，数组每一个元素都是一个指向</strong>file</strong>类型的指针，可想而知，这些指针都会指向一个打开的文件，并且file这一数据结构就是用来描述一个打开的文件的，<strong>而我们所说的文件描述符，实际上就是这个指针数组的索引。</strong>这也是为什么文件描述符是非负整数。</p>
<h2 id="文件表项"><a href="#文件表项" class="headerlink" title="文件表项"></a>文件表项</h2><p>前面说了，每一个打开文件实际上就是用一个<strong>file</strong>结构体进行描述的，在linux源码的<strong>include&#x2F;linux&#x2F;fs.h</strong>中可以找到其定义，定义如下:</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">file</span> &#123;</span></span><br><span class="line">	<span class="comment">/*</span></span><br><span class="line"><span class="comment">	 * fu_list becomes invalid after file_free is called and queued via</span></span><br><span class="line"><span class="comment">	 * fu_rcuhead for RCU freeing</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	<span class="class"><span class="keyword">union</span> &#123;</span></span><br><span class="line">		<span class="class"><span class="keyword">struct</span> <span class="title">list_head</span>	<span class="title">fu_list</span>;</span></span><br><span class="line">		<span class="class"><span class="keyword">struct</span> <span class="title">rcu_head</span> 	<span class="title">fu_rcuhead</span>;</span></span><br><span class="line">	&#125;f_u;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">path</span>		<span class="title">f_path</span>;</span></span><br><span class="line">	<span class="comment">//文件路径，包括目录项以及i-node</span></span><br><span class="line">	<span class="meta">#<span class="keyword">define</span> f_dentry	f_path.dentry</span></span><br><span class="line">	<span class="meta">#<span class="keyword">define</span> f_vfsmnt	f_path.mnt</span></span><br><span class="line">		<span class="type">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">file_operations</span>	*<span class="title">f_op</span>;</span></span><br><span class="line">	<span class="type">spinlock_t</span>		f_lock;</span><br><span class="line">	<span class="comment">/* f_ep_links, f_flags, no IRQ */</span></span><br><span class="line">	<span class="meta">#<span class="keyword">ifdef</span> CONFIG_SMP</span></span><br><span class="line">		<span class="type">int</span>			f_sb_list_cpu;</span><br><span class="line">	<span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line">		<span class="type">atomic_long_t</span>		f_count;</span><br><span class="line">	<span class="comment">//文件打开次数</span></span><br><span class="line">	<span class="type">unsigned</span> <span class="type">int</span> 		f_flags;</span><br><span class="line">	<span class="comment">//文件打开时的flag，对应于open函数的flag参数</span></span><br><span class="line">	<span class="type">fmode_t</span>			f_mode;</span><br><span class="line">	<span class="comment">//文件打开时的mode，对应于open函数的mode参数</span></span><br><span class="line">	<span class="type">loff_t</span>			f_pos;</span><br><span class="line">	<span class="comment">//文件偏移位置</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">fown_struct</span>	<span class="title">f_owner</span>;</span></span><br><span class="line">	<span class="type">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">cred</span>	*<span class="title">f_cred</span>;</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">file_ra_state</span>	<span class="title">f_ra</span>;</span></span><br><span class="line">	u64			f_version;</span><br><span class="line">	<span class="meta">#<span class="keyword">ifdef</span> CONFIG_SECURITY</span></span><br><span class="line">		<span class="type">void</span>			*f_security;</span><br><span class="line">	<span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line">	<span class="comment">/* needed for tty driver, and maybe others */</span></span><br><span class="line">	<span class="type">void</span>			*private_data;</span><br><span class="line">	<span class="meta">#<span class="keyword">ifdef</span> CONFIG_EPOLL</span></span><br><span class="line">	<span class="comment">/* Used by fs/eventpoll.c to link all the hooks to this file */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">list_head</span>	<span class="title">f_ep_links</span>;</span></span><br><span class="line">	<span class="meta">#<span class="keyword">endif</span> </span></span><br><span class="line">	<span class="comment">/* #ifdef CONFIG_EPOLL */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">address_space</span>	*<span class="title">f_mapping</span>;</span></span><br><span class="line">	<span class="meta">#<span class="keyword">ifdef</span> CONFIG_DEBUG_WRITECOUNT</span></span><br><span class="line">		<span class="type">unsigned</span> <span class="type">long</span> f_mnt_write_state;</span><br><span class="line">	<span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>





<p>在file结构体中，不得不再说一下它的f_path成员，这是一个<strong>struct path</strong>类型的变量，该类型定义于<strong>include&#x2F;linux&#x2F;path.h：</strong></p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">path</span> &#123;</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">vfsmount</span> *<span class="title">mnt</span>;</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">dentry</span> *<span class="title">dentry</span>;</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>



<p> 这里的dentry实际上就指向文件所在的<strong>目录项</strong>了，<strong>struct dentry</strong>的类型定义于<strong>include&#x2F;linux&#x2F;dcache.h：</strong></p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">dentry</span> &#123;</span></span><br><span class="line">	<span class="comment">/* RCU lookup touched fields */</span></span><br><span class="line">	<span class="type">unsigned</span> <span class="type">int</span> d_flags;</span><br><span class="line">	<span class="comment">/* protected by d_lock */</span></span><br><span class="line">	<span class="type">seqcount_t</span> d_seq;</span><br><span class="line">	<span class="comment">/* per dentry seqlock */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">hlist_bl_node</span> <span class="title">d_hash</span>;</span></span><br><span class="line">	<span class="comment">/* lookup hash list */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">dentry</span> *<span class="title">d_parent</span>;</span></span><br><span class="line">	<span class="comment">/* parent directory */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">qstr</span> <span class="title">d_name</span>;</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">inode</span> *<span class="title">d_inode</span>;</span> <span class="comment">// 注意这个</span></span><br><span class="line">	<span class="comment">/* Where the name belongs to - NULL is</span></span><br><span class="line"><span class="comment">					 * negative */</span></span><br><span class="line">	<span class="type">unsigned</span> <span class="type">char</span> d_iname[DNAME_INLINE_LEN];</span><br><span class="line">	<span class="comment">/* small names */</span></span><br><span class="line">	<span class="comment">/* Ref lookup also touches following */</span></span><br><span class="line">	<span class="type">unsigned</span> <span class="type">int</span> d_count;</span><br><span class="line">	<span class="comment">/* protected by d_lock */</span></span><br><span class="line">	<span class="type">spinlock_t</span> d_lock;</span><br><span class="line">	<span class="comment">/* per dentry lock */</span></span><br><span class="line">	<span class="type">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">dentry_operations</span> *<span class="title">d_op</span>;</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">super_block</span> *<span class="title">d_sb</span>;</span></span><br><span class="line">	<span class="comment">/* The root of the dentry tree */</span></span><br><span class="line">	<span class="type">unsigned</span> <span class="type">long</span> d_time;</span><br><span class="line">	<span class="comment">/* used by d_revalidate */</span></span><br><span class="line">	<span class="type">void</span> *d_fsdata;</span><br><span class="line">	<span class="comment">/* fs-specific data */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">list_head</span> <span class="title">d_lru</span>;</span></span><br><span class="line">	<span class="comment">/* LRU list */</span></span><br><span class="line">	<span class="comment">/*</span></span><br><span class="line"><span class="comment">	 * d_child and d_rcu can share memory</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	<span class="class"><span class="keyword">union</span> &#123;</span></span><br><span class="line">		<span class="class"><span class="keyword">struct</span> <span class="title">list_head</span> <span class="title">d_child</span>;</span></span><br><span class="line">		<span class="comment">/* child of parent list */</span></span><br><span class="line">		<span class="class"><span class="keyword">struct</span> <span class="title">rcu_head</span> <span class="title">d_rcu</span>;</span></span><br><span class="line">	&#125;d_u;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">list_head</span> <span class="title">d_subdirs</span>;</span></span><br><span class="line">	<span class="comment">/* our children */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">list_head</span> <span class="title">d_alias</span>;</span></span><br><span class="line">	<span class="comment">/* inode alias list */</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>在dentry结构体中，描述了根结点、父节点等等信息，尤其还要注意的是<strong>struct inode *d_inode</strong>这一变量，它则是指向了一个<strong>i-node</strong>结点。</p>
<p>再回到file结构体中，有一个<strong>struct file_operations *f_op</strong>变量，其类型定义在<strong>include&#x2F;linux&#x2F;fs.h</strong>中：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">file_operations</span> &#123;</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">module</span> *<span class="title">owner</span>;</span></span><br><span class="line">	<span class="type">loff_t</span> (*llseek) (<span class="keyword">struct</span> file *, <span class="type">loff_t</span>, <span class="type">int</span>);</span><br><span class="line">	<span class="type">ssize_t</span> (*read) (<span class="keyword">struct</span> file *, <span class="type">char</span> __user *, <span class="type">size_t</span>, <span class="type">loff_t</span> *);</span><br><span class="line">	<span class="type">ssize_t</span> (*write) (<span class="keyword">struct</span> file *, <span class="type">const</span> <span class="type">char</span> __user *, <span class="type">size_t</span>, <span class="type">loff_t</span> *);</span><br><span class="line">	<span class="type">ssize_t</span> (*aio_read) (<span class="keyword">struct</span> kiocb *, <span class="type">const</span> <span class="keyword">struct</span> iovec *, <span class="type">unsigned</span> <span class="type">long</span>, <span class="type">loff_t</span>);</span><br><span class="line">	<span class="type">ssize_t</span> (*aio_write) (<span class="keyword">struct</span> kiocb *, <span class="type">const</span> <span class="keyword">struct</span> iovec *, <span class="type">unsigned</span> <span class="type">long</span>, <span class="type">loff_t</span>);</span><br><span class="line">	<span class="type">int</span> (*readdir) (<span class="keyword">struct</span> file *, <span class="type">void</span> *, <span class="type">filldir_t</span>);</span><br><span class="line">	<span class="type">unsigned</span> <span class="title function_">int</span> <span class="params">(*poll)</span> <span class="params">(<span class="keyword">struct</span> file *, <span class="keyword">struct</span> poll_table_struct *)</span>;</span><br><span class="line">	<span class="type">long</span> (*unlocked_ioctl) (<span class="keyword">struct</span> file *, <span class="type">unsigned</span> <span class="type">int</span>, <span class="type">unsigned</span> <span class="type">long</span>);</span><br><span class="line">	<span class="type">long</span> (*compat_ioctl) (<span class="keyword">struct</span> file *, <span class="type">unsigned</span> <span class="type">int</span>, <span class="type">unsigned</span> <span class="type">long</span>);</span><br><span class="line">	<span class="type">int</span> (*mmap) (<span class="keyword">struct</span> file *, <span class="keyword">struct</span> vm_area_struct *);</span><br><span class="line">	<span class="type">int</span> (*open) (<span class="keyword">struct</span> inode *, <span class="keyword">struct</span> file *);</span><br><span class="line">	<span class="type">int</span> (*flush) (<span class="keyword">struct</span> file *, <span class="type">fl_owner_t</span> id);</span><br><span class="line">	<span class="type">int</span> (*release) (<span class="keyword">struct</span> inode *, <span class="keyword">struct</span> file *);</span><br><span class="line">	<span class="type">int</span> (*fsync) (<span class="keyword">struct</span> file *, <span class="type">int</span> datasync);</span><br><span class="line">	<span class="type">int</span> (*aio_fsync) (<span class="keyword">struct</span> kiocb *, <span class="type">int</span> datasync);</span><br><span class="line">	<span class="type">int</span> (*fasync) (<span class="type">int</span>, <span class="keyword">struct</span> file *, <span class="type">int</span>);</span><br><span class="line">	<span class="type">int</span> (*lock) (<span class="keyword">struct</span> file *, <span class="type">int</span>, <span class="keyword">struct</span> file_lock *);</span><br><span class="line">	<span class="type">ssize_t</span> (*sendpage) (<span class="keyword">struct</span> file *, <span class="keyword">struct</span> page *, <span class="type">int</span>, <span class="type">size_t</span>, <span class="type">loff_t</span> *, <span class="type">int</span>);</span><br><span class="line">	<span class="type">unsigned</span> <span class="title function_">long</span> <span class="params">(*get_unmapped_area)</span><span class="params">(<span class="keyword">struct</span> file *, <span class="type">unsigned</span> <span class="type">long</span>, <span class="type">unsigned</span> <span class="type">long</span>, <span class="type">unsigned</span> <span class="type">long</span>, <span class="type">unsigned</span> <span class="type">long</span>)</span>;</span><br><span class="line">	<span class="type">int</span> (*check_flags)(<span class="type">int</span>);</span><br><span class="line">	<span class="type">int</span> (*flock) (<span class="keyword">struct</span> file *, <span class="type">int</span>, <span class="keyword">struct</span> file_lock *);</span><br><span class="line">	<span class="type">ssize_t</span> (*splice_write)(<span class="keyword">struct</span> pipe_inode_info *, <span class="keyword">struct</span> file *, <span class="type">loff_t</span> *, <span class="type">size_t</span>, <span class="type">unsigned</span> <span class="type">int</span>);</span><br><span class="line">	<span class="type">ssize_t</span> (*splice_read)(<span class="keyword">struct</span> file *, <span class="type">loff_t</span> *, <span class="keyword">struct</span> pipe_inode_info *, <span class="type">size_t</span>, <span class="type">unsigned</span> <span class="type">int</span>);</span><br><span class="line">	<span class="type">int</span> (*setlease)(<span class="keyword">struct</span> file *, <span class="type">long</span>, <span class="keyword">struct</span> file_lock **);</span><br><span class="line">	<span class="type">long</span> (*fallocate)(<span class="keyword">struct</span> file *file, <span class="type">int</span> mode, <span class="type">loff_t</span> offset,</span><br><span class="line">				  <span class="type">loff_t</span> len);</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>



<p>可见，在该成员中包含了所有文件操作相关的函数指针。</p>
<p>每一个打开的文件都对应于一个file结构体，在该结构体中，f_flags描述了文件标志，f_pos描述了文件的偏移位置，而在f_path中有含有一个指向一个inode结点的指针。</p>
<p>因此可以知道，文件表项的数据结构就是file结构体，而在实际上内核中也并不存在这样一张文件表，只是每个打开的文件都对应一个file结构体，也就是一个文件表项，**打开文件描述符表struct file fd_array[NR_OPEN_DEFAULT]**数组中的每一项都会指向这样一个文件表项，如下图所示：</p>
<img src="fd2.png" style="zoom:80%;" />



<h2 id="Inode"><a href="#Inode" class="headerlink" title="Inode"></a>Inode</h2><p>第三种数据结构就是inode节点，在<strong>include&#x2F;linux&#x2F;fs.h</strong>中找到其定义如下：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">inode</span> &#123;</span></span><br><span class="line">	<span class="comment">/* RCU path lookup touches following: */</span></span><br><span class="line">	<span class="type">umode_t</span>			i_mode;</span><br><span class="line">	<span class="comment">//权限</span></span><br><span class="line">	<span class="type">uid_t</span>			i_uid;</span><br><span class="line">	<span class="comment">//用户id</span></span><br><span class="line">	<span class="type">gid_t</span>			i_gid;</span><br><span class="line">	<span class="comment">//组id</span></span><br><span class="line">	<span class="type">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">inode_operations</span>	*<span class="title">i_op</span>;</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">super_block</span>	*<span class="title">i_sb</span>;</span></span><br><span class="line">	<span class="type">spinlock_t</span>		i_lock;</span><br><span class="line">	<span class="comment">/* i_blocks, i_bytes, maybe i_size */</span></span><br><span class="line">	<span class="type">unsigned</span> <span class="type">int</span>		i_flags;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">mutex</span>		<span class="title">i_mutex</span>;</span></span><br><span class="line">	<span class="type">unsigned</span> <span class="type">long</span>		i_state;</span><br><span class="line">	<span class="type">unsigned</span> <span class="type">long</span>		dirtied_when;</span><br><span class="line">	<span class="comment">/* jiffies of first dirtying */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">hlist_node</span>	<span class="title">i_hash</span>;</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">list_head</span>	<span class="title">i_wb_list</span>;</span></span><br><span class="line">	<span class="comment">/* backing dev IO list */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">list_head</span>	<span class="title">i_lru</span>;</span></span><br><span class="line">	<span class="comment">/* inode LRU list */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">list_head</span>	<span class="title">i_sb_list</span>;</span></span><br><span class="line">	<span class="class"><span class="keyword">union</span> &#123;</span></span><br><span class="line">		<span class="class"><span class="keyword">struct</span> <span class="title">list_head</span>	<span class="title">i_dentry</span>;</span></span><br><span class="line">		<span class="class"><span class="keyword">struct</span> <span class="title">rcu_head</span>		<span class="title">i_rcu</span>;</span></span><br><span class="line">	&#125;;</span><br><span class="line">	<span class="type">unsigned</span> <span class="type">long</span>		i_ino;</span><br><span class="line">	<span class="comment">//inode节点号</span></span><br><span class="line">	<span class="type">atomic_t</span>		i_count;</span><br><span class="line">	<span class="type">unsigned</span> <span class="type">int</span>		i_nlink;</span><br><span class="line">	<span class="type">dev_t</span>			i_rdev;</span><br><span class="line">	<span class="type">unsigned</span> <span class="type">int</span>		i_blkbits;</span><br><span class="line">	u64			i_version;</span><br><span class="line">	<span class="type">loff_t</span>			i_size;</span><br><span class="line">	<span class="comment">//文件大小</span></span><br><span class="line">	<span class="meta">#<span class="keyword">ifdef</span> __NEED_I_SIZE_ORDERED</span></span><br><span class="line">		<span class="type">seqcount_t</span>		i_size_seqcount;</span><br><span class="line">	<span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line">		<span class="class"><span class="keyword">struct</span> <span class="title">timespec</span>		<span class="title">i_atime</span>;</span></span><br><span class="line">	<span class="comment">//最后一次访问(access)的时间</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">timespec</span>		<span class="title">i_mtime</span>;</span></span><br><span class="line">	<span class="comment">//最后一次修改(modify)的时间</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">timespec</span>		<span class="title">i_ctime</span>;</span></span><br><span class="line">	<span class="comment">//最后一次改变(change)的时间</span></span><br><span class="line">	<span class="type">blkcnt_t</span>		i_blocks;</span><br><span class="line">	<span class="comment">//块数</span></span><br><span class="line">	<span class="type">unsigned</span> <span class="type">short</span>          i_bytes;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">rw_semaphore</span>	<span class="title">i_alloc_sem</span>;</span></span><br><span class="line">	<span class="type">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">file_operations</span>	*<span class="title">i_fop</span>;</span></span><br><span class="line">	<span class="comment">/* former -&gt;i_op-&gt;default_file_ops */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">file_lock</span>	*<span class="title">i_flock</span>;</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">address_space</span>	*<span class="title">i_mapping</span>;</span></span><br><span class="line">	<span class="comment">//块地址映射</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">address_space</span>	<span class="title">i_data</span>;</span></span><br><span class="line">	<span class="meta">#<span class="keyword">ifdef</span> CONFIG_QUOTA</span></span><br><span class="line">		<span class="class"><span class="keyword">struct</span> <span class="title">dquot</span>		*<span class="title">i_dquot</span>[<span class="title">MAXQUOTAS</span>];</span></span><br><span class="line">	<span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line">		<span class="class"><span class="keyword">struct</span> <span class="title">list_head</span>	<span class="title">i_devices</span>;</span></span><br><span class="line">	<span class="class"><span class="keyword">union</span> &#123;</span></span><br><span class="line">		<span class="class"><span class="keyword">struct</span> <span class="title">pipe_inode_info</span>	*<span class="title">i_pipe</span>;</span></span><br><span class="line">		<span class="class"><span class="keyword">struct</span> <span class="title">block_device</span>	*<span class="title">i_bdev</span>;</span></span><br><span class="line">		<span class="class"><span class="keyword">struct</span> <span class="title">cdev</span>		*<span class="title">i_cdev</span>;</span></span><br><span class="line">	&#125;;</span><br><span class="line">	__u32			i_generation;</span><br><span class="line">	<span class="meta">#<span class="keyword">ifdef</span> CONFIG_FSNOTIFY</span></span><br><span class="line">		__u32			i_fsnotify_mask;</span><br><span class="line">	<span class="comment">/* all events this inode cares about */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">hlist_head</span>	<span class="title">i_fsnotify_marks</span>;</span></span><br><span class="line">	<span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line">	<span class="meta">#<span class="keyword">ifdef</span> CONFIG_IMA</span></span><br><span class="line">		<span class="type">atomic_t</span>		i_readcount;</span><br><span class="line">	<span class="comment">/* struct files open RO */</span></span><br><span class="line">	<span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line">		<span class="type">atomic_t</span>		i_writecount;</span><br><span class="line">	<span class="meta">#<span class="keyword">ifdef</span> CONFIG_SECURITY</span></span><br><span class="line">		<span class="type">void</span>			*i_security;</span><br><span class="line">	<span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line">	<span class="meta">#<span class="keyword">ifdef</span> CONFIG_FS_POSIX_ACL</span></span><br><span class="line">		<span class="class"><span class="keyword">struct</span> <span class="title">posix_acl</span>	*<span class="title">i_acl</span>;</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">posix_acl</span>	*<span class="title">i_default_acl</span>;</span></span><br><span class="line">	<span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line">		<span class="type">void</span>			*i_private;</span><br><span class="line">	<span class="comment">/* fs or device private pointer */</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p> 代码中只注释了一部分，通过inode结构，可以知道<strong>文件数据块的在磁盘上的位置以及文件大小</strong>等信息，这样才能使得<strong>进程能够通过file结构体来找到磁盘上相应文件的位置</strong>来进行文件读写。</p>
<p> 另外补充一点，关于inode结构体中的<strong>struct inode_operations *i_op</strong>成员，其数据结构定义在<strong>include&#x2F;linux&#x2F;fs.h</strong>中：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">inode_operations</span> &#123;</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">dentry</span> * (*<span class="title">lookup</span>) (<span class="keyword">struct</span> <span class="title">inode</span> *,<span class="keyword">struct</span> <span class="title">dentry</span> *, <span class="keyword">struct</span> <span class="title">nameidata</span> *);</span></span><br><span class="line">	<span class="type">void</span> * (*follow_link) (<span class="keyword">struct</span> dentry *, <span class="keyword">struct</span> nameidata *);</span><br><span class="line">	<span class="type">int</span> (*permission) (<span class="keyword">struct</span> inode *, <span class="type">int</span>, <span class="type">unsigned</span> <span class="type">int</span>);</span><br><span class="line">	<span class="type">int</span> (*check_acl)(<span class="keyword">struct</span> inode *, <span class="type">int</span>, <span class="type">unsigned</span> <span class="type">int</span>);</span><br><span class="line">	<span class="type">int</span> (*readlink) (<span class="keyword">struct</span> dentry *, <span class="type">char</span> __user *,<span class="type">int</span>);</span><br><span class="line">	<span class="type">void</span> (*put_link) (<span class="keyword">struct</span> dentry *, <span class="keyword">struct</span> nameidata *, <span class="type">void</span> *);</span><br><span class="line">	<span class="type">int</span> (*create) (<span class="keyword">struct</span> inode *,<span class="keyword">struct</span> dentry *,<span class="type">int</span>, <span class="keyword">struct</span> nameidata *);</span><br><span class="line">	<span class="type">int</span> (*link) (<span class="keyword">struct</span> dentry *,<span class="keyword">struct</span> inode *,<span class="keyword">struct</span> dentry *);</span><br><span class="line">	<span class="type">int</span> (*unlink) (<span class="keyword">struct</span> inode *,<span class="keyword">struct</span> dentry *);</span><br><span class="line">	<span class="type">int</span> (*symlink) (<span class="keyword">struct</span> inode *,<span class="keyword">struct</span> dentry *,<span class="type">const</span> <span class="type">char</span> *);</span><br><span class="line">	<span class="type">int</span> (*mkdir) (<span class="keyword">struct</span> inode *,<span class="keyword">struct</span> dentry *,<span class="type">int</span>);</span><br><span class="line">	<span class="type">int</span> (*rmdir) (<span class="keyword">struct</span> inode *,<span class="keyword">struct</span> dentry *);</span><br><span class="line">	<span class="type">int</span> (*mknod) (<span class="keyword">struct</span> inode *,<span class="keyword">struct</span> dentry *,<span class="type">int</span>,<span class="type">dev_t</span>);</span><br><span class="line">	<span class="type">int</span> (*rename) (<span class="keyword">struct</span> inode *, <span class="keyword">struct</span> dentry *,</span><br><span class="line">				<span class="keyword">struct</span> inode *, <span class="keyword">struct</span> dentry *);</span><br><span class="line">	<span class="type">void</span> (*truncate) (<span class="keyword">struct</span> inode *);</span><br><span class="line">	<span class="type">int</span> (*setattr) (<span class="keyword">struct</span> dentry *, <span class="keyword">struct</span> iattr *);</span><br><span class="line">	<span class="type">int</span> (*getattr) (<span class="keyword">struct</span> vfsmount *mnt, <span class="keyword">struct</span> dentry *, <span class="keyword">struct</span> kstat *);</span><br><span class="line">	<span class="type">int</span> (*setxattr) (<span class="keyword">struct</span> dentry *, <span class="type">const</span> <span class="type">char</span> *,<span class="type">const</span> <span class="type">void</span> *,<span class="type">size_t</span>,<span class="type">int</span>);</span><br><span class="line">	<span class="type">ssize_t</span> (*getxattr) (<span class="keyword">struct</span> dentry *, <span class="type">const</span> <span class="type">char</span> *, <span class="type">void</span> *, <span class="type">size_t</span>);</span><br><span class="line">	<span class="type">ssize_t</span> (*listxattr) (<span class="keyword">struct</span> dentry *, <span class="type">char</span> *, <span class="type">size_t</span>);</span><br><span class="line">	<span class="type">int</span> (*removexattr) (<span class="keyword">struct</span> dentry *, <span class="type">const</span> <span class="type">char</span> *);</span><br><span class="line">	<span class="type">void</span> (*truncate_range)(<span class="keyword">struct</span> inode *, <span class="type">loff_t</span>, <span class="type">loff_t</span>);</span><br><span class="line">	<span class="type">int</span> (*fiemap)(<span class="keyword">struct</span> inode *, <span class="keyword">struct</span> fiemap_extent_info *, u64 start,</span><br><span class="line">			      u64 len);</span><br><span class="line">&#125;____cacheline_aligned;</span><br></pre></td></tr></table></figure>

<p> 可见，在该成员变量所指向的数据结构中，包含了许多函数指针，这些函数指针大多针对于目录、文件操作。</p>
<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p> 进程、打开文件描述符表、文件表项和i-node结点关系如图所示。（暂时忽略进程中0、1和2号文件描述符分别默认为标准输入、标准输出和标准错误的情况）</p>
<p><img src="/2021/11/20/Linux%E6%96%87%E4%BB%B6%E6%8F%8F%E8%BF%B0%E7%AC%A6%E7%9A%84%E5%AE%9E%E7%8E%B0/fd1.png"></p>
<p>通过以上分析，我们可以得出以下结论：</p>
<ol>
<li><p>每启动一个进程都会为其分配一个<code>task_struct</code>结构体，在task_struct结构体中含有一个<code>file_struct</code>结构体指针，其所指向的file_struct结构体中，含有一个file的指针数组<code>fd_array</code>,它就是<strong>打开文件描述符表</strong>，其中<strong>每一个元素都指向一个文件表项</strong>，这个<strong>数组的索引就是文件描述符</strong>。此外，file_struct结构体中的next_fd保存的是下一个分配的文件描述符，它会在调用open和close改变，最终使得每次open返回的都是当前可用的<strong>最小文件描述符</strong>；</p>
</li>
<li><p>每次调用open或者create(内部实际上还是调用的open)，都会对新打开的文件分配一个file结构体，并且将打开文件的标志、状态、权限等信息填入这个file结构体中。<strong>这个file结构体也叫文件表项</strong>；</p>
</li>
<li><p><strong>磁盘中的每个文件都对应一个i-node</strong>，<strong>每一个文件表项都会指向一个文件的i-node</strong>，<strong>但是同一文件的i-node可以对应多个文件表项（</strong>当多次调用open打开同一个文件时就会出现这种情况，不管是同一进程多次打开同一文件（如图中A进程的0号和2号文件描述符对应两个文件表项，但是最终指向同一i-node即同一文件），还是不同进程多次打开同一文件（如图中A进程3号文件描述符和B进程的3号文件描述符））；</p>
</li>
<li><p><strong>同一进程下的不同文件描述符是可以指向同一文件表项</strong>，即最终指向同一文件<strong>（如图中A进程的0号文件描述符和1号文件描述符，使用dup函数即可实现）。</strong></p>
</li>
<li><p>子进程在创建时会拷贝父进程的打开文件描述符表，因此<strong>父子进程是共享文件表项</strong>的。而相互独立的不同进程的打开文件描述符表是相互独立的，因此相互独立的多个进程之间的文件描述符可以相同，但是不同进程的文件描述符是不能指向同一文件表项的（<strong>除非这个文件描述符是从同一个祖先进程中继承得来的</strong>），但是这并不妨碍不同进程访问同一文件（如第3点结论）；</p>
</li>
<li><p>指向同一文件表项的不同文件描述符（不同进程相同数值的文件描述符也看做不同）共享文件标志、文件偏移等信息；</p>
</li>
<li><p>每一个文件表项对应的file结构体中的<code>f_count</code>会记录通过该文件表项打开文件的次数，当<code>f_count</code>计数归0时这个文件表项才会被删除，因此，对于指向同一文件表项的两个不同文件描述符（如子进程所继承的父进程的文件描述符，或同一进程中dup的两个文件描述符指向同一个文件表项），即使其中一个文件描述符关闭了，只要仍然有文件描述符指向这个文件表项，那么就依然能通过这个文件表项访问文件，直到所有指向该文件表项的文件描述符都关闭了才不能再进行访问；</p>
</li>
</ol>
<blockquote>
<p>参考链接</p>
<p><a target="_blank" rel="noopener" href="https://zh.wikipedia.org/wiki/%E6%96%87%E4%BB%B6%E6%8F%8F%E8%BF%B0%E7%AC%A6">文件描述符</a></p>
<p><a target="_blank" rel="noopener" href="https://www.cnblogs.com/lwyeric/p/13598704.html">Linux中文件描述符的理解</a></p>
</blockquote>

    </div>

    
    
    

    <footer class="post-footer">
          <div class="post-tags">
              <a href="/tags/Linux/" rel="tag"># Linux</a>
              <a href="/tags/File/" rel="tag"># File</a>
          </div>

        

          <div class="post-nav">
            <div class="post-nav-item">
                <a href="/2021/11/20/Linux%E5%A4%9A%E8%BF%9B%E7%A8%8B%E3%80%81%E5%A4%9A%E7%BA%BF%E7%A8%8B%E7%BC%96%E7%A8%8B/" rel="prev" title="Linux多进程、多线程编程">
                  <i class="fa fa-chevron-left"></i> Linux多进程、多线程编程
                </a>
            </div>
            <div class="post-nav-item">
                <a href="/2021/11/22/Linux%E7%9A%84mmap%E6%A6%82%E5%BF%B5%E3%80%81%E5%8E%9F%E7%90%86%E3%80%81%E4%BD%BF%E7%94%A8/" rel="next" title="Linux的mmap概念、原理、使用">
                  Linux的mmap概念、原理、使用 <i class="fa fa-chevron-right"></i>
                </a>
            </div>
          </div>
    </footer>
  </article>
</div>






</div>
  </main>

  <footer class="footer">
    <div class="footer-inner">


<div class="copyright">
  &copy; 
  <span itemprop="copyrightYear">2023</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">SongyangJi</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" rel="noopener" target="_blank">Hexo</a> & <a href="https://theme-next.js.org/muse/" rel="noopener" target="_blank">NexT.Muse</a> 强力驱动
  </div>

    </div>
  </footer>

  
  <div class="toggle sidebar-toggle" role="button">
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
  </div>
  <div class="sidebar-dimmer"></div>
  <div class="back-to-top" role="button" aria-label="返回顶部">
    <i class="fa fa-arrow-up fa-lg"></i>
    <span>0%</span>
  </div>

<noscript>
  <div class="noscript-warning">Theme NexT works best with JavaScript enabled</div>
</noscript>


  
  <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js" integrity="sha256-XL2inqUJaslATFnHdJOi9GfQ60on8Wx1C2H8DYiN1xY=" crossorigin="anonymous"></script>
<script src="/js/comments.js"></script><script src="/js/utils.js"></script><script src="/js/motion.js"></script><script src="/js/schemes/muse.js"></script><script src="/js/next-boot.js"></script>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/hexo-generator-searchdb/1.4.1/search.js" integrity="sha256-1kfA5uHPf65M5cphT2dvymhkuyHPQp5A53EGZOnOLmc=" crossorigin="anonymous"></script>
<script src="/js/third-party/search/local-search.js"></script>





  





</body>
</html>
